package com.iwdnb.gkgz.common.utils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

import com.iwdnb.bmnf.common.utils.BeanConvertUtils;
import com.iwdnb.gkgz.common.model.dto.StockDayData;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

/**
 * 代码解释：
 * 数据模拟：
 *
 * overnightReturns 是一个示例列表，包含成分股的隔夜收益率。在实际应用中，你可能需要从API或数据库中获取这些数据。
 * 均值和分位数的计算：
 *
 * 使用 calculateMean 方法计算收益率的均值。
 * 使用 calculatePercentile 方法计算 5% 和 95% 的分位数。
 * 情绪判断：
 *
 * 根据给定的 closeRate（当日收益率），与计算得出的分位数和均值进行比较，输出相应的情绪分析结果。
 * 替代数据来源：
 * 在实际部署中，您可以使用股票行情API（如腾讯财经、Wind、聚宽等）来获取实时的成分股数据，并替换这些模拟数据。
 */
@Slf4j
public class EmotionAnalysis {
    public static final int COLD_EMOTION = 1;
    public static final int NORMAL_EMOTION = 5;
    public static final int HOT_EMOTION = 9;

    public static EmotionData caculateOpenEmotion(List<StockDayData> stockDayDataList) {
        stockDayDataList = BeanConvertUtils.convertList(stockDayDataList, StockDayData.class);
        for (StockDayData stockDayData : stockDayDataList) {
            stockDayData.setClosePrice(stockDayData.getOpenPrice());
        }
        return caculateEmotion(stockDayDataList);
    }

    public static EmotionData caculateEmotion(List<StockDayData> stockDayDataList) {
        // 模拟成分股的隔夜收益率
        List<Double> overnightProfits = new ArrayList<>();
        List<Double> closeProfits = new ArrayList<>();
        for (StockDayData stockDayData : stockDayDataList) {
            BigDecimal beforeClosePrice = stockDayData.getBeforeClosePrice();
            if (Objects.isNull(beforeClosePrice)) {
                beforeClosePrice = stockDayData.getOpenPrice();
            }
            BigDecimal openRate = BigDecimalUtils.subStractAndDividePrecent(stockDayData.getOpenPrice(),
                beforeClosePrice);
            BigDecimal closeRate = BigDecimalUtils.subStractAndDividePrecent(stockDayData.getClosePrice(),
                beforeClosePrice);
            overnightProfits.add(openRate.doubleValue());
            closeProfits.add(closeRate.doubleValue());
        }
        // 今天的闭市收益率
        double closeRate = calculateAvg(closeProfits);
        // 计算均值、5%分位和95%分位
        double overnightRate = calculateAvg(overnightProfits);
        //排序
        Collections.sort(overnightProfits);
        double minPercentile = calculatePercentile(overnightProfits, 5);
        double lowPercentile = calculatePercentile(overnightProfits, 10);
        double middlePercentile = calculatePercentile(overnightProfits, 50);
        double highPercentile = calculatePercentile(overnightProfits, 90);
        double maxPercentile = calculatePercentile(overnightProfits, 95);

        // 情绪判断
        return analyzeEmotion(closeRate, minPercentile, lowPercentile, middlePercentile, highPercentile, maxPercentile,
            overnightRate);
    }

    private static double calculateAvg(List<Double> values) {
        double sum = 0;
        for (double value : values) {
            sum += value;
        }
        return sum / values.size();
    }

    private static double calculatePercentile(List<Double> values, double percentile) {
        int index = (int)Math.ceil(percentile / 100 * values.size()) - 1;
        return values.get(index);
    }

    private static EmotionData analyzeEmotion(double closeRate, double minPercentile, double lowPercentile,
        double middlePercentile, double highPercentile, double maxPercentile, double overnightRate) {
        log.info("closeRate:{},overnightRate:{},min:{},low:{},middle:{},high:{},max:{}", BigDecimalUtils.of(closeRate),
            BigDecimalUtils.of(overnightRate), BigDecimalUtils.of(minPercentile), BigDecimalUtils.of(lowPercentile),
            BigDecimalUtils.of(middlePercentile), BigDecimalUtils.of(highPercentile),
            BigDecimalUtils.of(maxPercentile));
        overnightRate = overnightRate * 0.5;
        EmotionData data = new EmotionData();
        data.setCurrentValue(BigDecimalUtils.of(closeRate));
        data.setMinValue(BigDecimalUtils.of(minPercentile - overnightRate));
        data.setLowValue(BigDecimalUtils.of(lowPercentile - overnightRate));
        data.setHighValue(BigDecimalUtils.of(highPercentile + overnightRate));
        data.setMaxValue(BigDecimalUtils.of(maxPercentile + overnightRate));
        if (closeRate < minPercentile - overnightRate) {
            log.info("情绪冰点，空仓");
            data.setEmotionValue(1);
        } else if (closeRate < lowPercentile - overnightRate) {
            log.info("情绪转冷，减仓");
            data.setEmotionValue(3);
        } else if (closeRate < highPercentile + overnightRate) {
            log.info("静观其变");
            data.setEmotionValue(5);
        } else if (closeRate < maxPercentile + overnightRate) {
            log.info("情绪转暖，加仓");
            data.setEmotionValue(7);
        } else {
            log.info("情绪火热，满仓");
            data.setEmotionValue(9);
        }
        return data;
    }

    public static boolean isMarkEmotion(int emotion) {
        return emotion == 1 || emotion == 7 || emotion == 9;
    }

    public static boolean isColdEmotion(int emotion) {
        return emotion == 1;
    }

    public static boolean isHotEmotion(int emotion) {
        return emotion == 9;
    }

    public static boolean isActiveEmotion(int emotion) {
        return emotion >= 7;
    }

    public static boolean isNegativeEmotion(int emotion) {
        return emotion <= 3;
    }

    public static boolean isSensitiveEmotion(int emotion) {
        return emotion == 5;
    }

    @Data
    public static class EmotionData {
        private BigDecimal currentValue;

        private BigDecimal minValue;

        private BigDecimal lowValue;

        private BigDecimal highValue;

        private BigDecimal maxValue;

        private Integer emotionValue;
    }
}
